﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Linq;
using Hxsoft.AppV1;

namespace Hxsoft.AppV1.Module
{
	public partial class PageBlock : ICreator { }




	/// <summary>
	/// PageBlocks 类。
	/// </summary>
	public static partial class PageBlocks
	{
		public const string INFO_TYPE = "PageBlock";



		#region GetItem
		/// <summary>
		/// 根据标识获取指定的页面块。
		/// </summary>
		/// <param name="o">页面块集合。</param>
		/// <param name="blockId">获取的页面块标识 BlockId。</param>
		/// <returns>获取的信息项。</returns>
		public static PageBlock GetItem(this System.Data.Linq.Table<PageBlock> o, int blockId)
		{
			return o.SingleOrDefault(p => p.BlockId == blockId);
		}

		public static PageBlock GetItem(int blockId)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;
			return dc.PageBlocks.GetItem(blockId);
		}

		/// <summary>
		/// 根据指定信息获取页面块。
		/// </summary>
		/// <param name="o">页面块集合。</param>
		/// <param name="siteId">所属站点。</param>
		/// <param name="code">块代码。</param>
		/// <returns>指定的页面块。</returns>
		public static PageBlock GetItem(this System.Data.Linq.Table<PageBlock> o, int siteId, string code)
		{
			return o.SingleOrDefault(p => p.SiteId == siteId && p.Code == code);
		}

		public static PageBlock GetItem(int siteId, string code)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;
			return dc.PageBlocks.GetItem(siteId, code);
		}
		#endregion



		#region Exists
		/// <summary>
		/// 验证指定的页面块是否已经存在。
		/// </summary>
		/// <param name="o">页面块集合。</param>
		/// <param name="blockId">验证的页面块标识 BlockId。</param>
		/// <returns>布尔值表示指定的页面块是否已经存在。</returns>
		public static bool Exists(this System.Data.Linq.Table<PageBlock> o, int blockId)
		{
			return o.Any(p => p.BlockId == blockId);
		}

		public static bool Exists(int blockId)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;
			return dc.PageBlocks.Exists(blockId);
		}

		/// <summary>
		/// 验证指定的页面块是否已经存在。
		/// </summary>
		/// <param name="o">页面块集合。</param>
		/// <param name="siteId">所属站点。</param>
		/// <param name="code">块代码。</param>
		/// <returns>布尔值表示指定的页面块是否已经存在。</returns>
		public static bool Exists(this System.Data.Linq.Table<PageBlock> o, int siteId, string code)
		{
			return o.Any(p => p.SiteId == siteId && p.Code == code);
		}

		public static bool Exists(int siteId, string code)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;
			return dc.PageBlocks.Exists(siteId, code);
		}
		#endregion
	}



	/// <summary>
	/// PageBlocks 类操作部分。
	/// </summary>
	public static partial class PageBlocks
	{
		#region Insert
		/// <summary>
		/// 添加页面块。
		/// </summary>
		/// <param name="insertedBlock">添加的页面块。</param>
		/// <returns>添加的页面块。</returns>
		private static PageBlock Insert(PageBlock insertedBlock, RightCheckMethod<GenericModuleDataContext, PageBlock> check)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();

			PageBlock block = insertedBlock.ToNewEntity<PageBlock>();
			block.CreatorId = Users.CurrentUserId;
			block.CreationDate = DateTime.Now;

			if (check != null) check(dc, block, true);	// 权限验证

			if (dc.PageBlocks.Exists(block.SiteId, block.Code))
				throw new ObjectExistsException(Res.PageBlocks_ExistsCode);

			dc.PageBlocks.InsertOnSubmit(block);
			dc.SubmitChanges();

			// 持久化资源
			InfoItems.SetPersistent(dc, block.GlobalId, true);

			// 注册权限
			RegisterPageBlockEditPermission(block);

			// 记录日志
			Logs.Insert(dc, ResourceId, (int)PermissionCode.Insert, INFO_TYPE, block.BlockId.ToString(), PermissionCode.Insert.ToString(), block.Name);

			// 返回只读数据
			return insertedBlock.FillByEntity(block);
		}



		/// <summary>
		/// 添加页面块。
		/// </summary>
		/// <param name="insertedBlock">添加的页面块。</param>
		/// <returns>添加的页面块。</returns>
		internal static PageBlock _Insert(PageBlock insertedBlock)
		{
			return Insert(insertedBlock, null);
		}



		/// <summary>
		/// 添加页面块。
		/// </summary>
		/// <param name="insertedBlock">添加的页面块。</param>
		/// <returns>添加的页面块。</returns>
		public static PageBlock Insert(PageBlock insertedBlock)
		{
			insertedBlock.IsHidden = false;
			return Insert(insertedBlock, (GenericModuleDataContext dc, PageBlock block, bool triggerException) => GetInsertRight(dc, block, triggerException));
		}
		#endregion



		#region Update
		private static readonly HashSet<string> _updatedColumns = typeof(PageBlock).GetEntityColumnNames(new string[] {
				"Name",
				"Content"
			}, true);

		/// <summary>
		/// 修改页面块。
		/// </summary>
		/// <param name="updatedBlock">修改的页面块。</param>
		/// <returns>修改的页面块。</returns>
		private static PageBlock Update(PageBlock updatedBlock, RightCheckMethod<GenericModuleDataContext, PageBlock> check)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();

			PageBlock block = dc.PageBlocks.GetItem(updatedBlock.BlockId);
			if (block == null)
				throw new ObjectNotExistsException(Res.Operation_ObjectNotExists);

			if (check != null) check(dc, block, true);	// 权限验证

			block.FillByEntity(updatedBlock, _updatedColumns);

			try
			{
				dc.SubmitChanges(ConflictMode.ContinueOnConflict);
			}
			catch (ChangeConflictException e)
			{
				foreach (ObjectChangeConflict occ in dc.ChangeConflicts)
				{
					occ.Resolve(RefreshMode.KeepCurrentValues);
				}
			}

			// 持久化资源
			InfoItems.SetPersistent(dc, block.GlobalId, true);

			// 注册权限
			RegisterPageBlockEditPermission(block);

			// 记录日志
			Logs.Insert(dc, ResourceId, (int)PermissionCode.Update, INFO_TYPE, block.BlockId.ToString(), PermissionCode.Update.ToString(), block.Name);

			// 返回只读数据
			return updatedBlock.FillByEntity(block);
		}



		/// <summary>
		/// 修改页面块。
		/// </summary>
		/// <param name="updatedBlock">修改的页面块。</param>
		/// <returns>修改的页面块。</returns>
		internal static PageBlock _Update(PageBlock updatedBlock)
		{
			return Update(updatedBlock, null);
		}



		/// <summary>
		/// 修改页面块。
		/// </summary>
		/// <param name="updatedBlock">修改的页面块。</param>
		/// <returns>修改的页面块。</returns>
		public static PageBlock Update(PageBlock updatedBlock)
		{
			return Update(updatedBlock, (GenericModuleDataContext dc, PageBlock block, bool triggerException) => GetUpdateRight(dc, block, triggerException));
		}
		#endregion



		#region Delete
		/// <summary>
		/// 删除页面块。
		/// </summary>
		/// <param name="blockId">删除的页面块标识 BlockId。</param>
		private static void Delete(int blockId, RightCheckMethod<GenericModuleDataContext, PageBlock> check)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();

			PageBlock block = dc.PageBlocks.GetItem(blockId);
			if (block == null)
				throw new ObjectNotExistsException(Res.Operation_ObjectNotExists);

			if (check != null) check(dc, block, true);	// 权限验证

			Delete(dc, block);

			dc.SubmitChanges();

			// 记录日志
			Logs.Insert(dc, ResourceId, (int)PermissionCode.Delete, INFO_TYPE, block.BlockId.ToString(), PermissionCode.Delete.ToString(), block.Name);
		}



		/// <summary>
		/// 删除页面块。
		/// </summary>
		/// <param name="blockId">删除的页面块标识 BlockId。</param>
		internal static void _Delete(int blockId)
		{
			Delete(blockId, null);
		}



		/// <summary>
		/// 删除页面块。
		/// </summary>
		/// <param name="blockId">删除的页面块标识 BlockId。</param>
		public static void Delete(int blockId)
		{
			Delete(blockId, (GenericModuleDataContext dc, PageBlock block, bool triggerException) => GetDeleteRight(dc, block, triggerException));
		}

		#region internal Delete
		internal static void Delete(GenericModuleDataContext dc, PageBlock block)
		{
			dc.PageBlocks.DeleteOnSubmit(block);

			// 删除资源
			InfoItem infoItem = dc.InfoItems.GetItem(block.GlobalId);
			if (infoItem != null)
				InfoItems.Delete(dc, infoItem);
			// 删除权限注册
			Resource resource = dc.Resources.GetItem(BlockEditResourceCategoryId, block.SiteId, GetBlockEditResourceCode(block.BlockId));
			if (resource != null)
				Resources.Delete(dc, resource);
		}

		internal static void DeleteByParent(GenericModuleDataContext dc, Site parent)
		{
			IEnumerable<PageBlock> e = parent.PageBlocks.AsEnumerable();
			foreach (PageBlock i in e)
				Delete(dc, i);
		}
		#endregion
		#endregion



		#region Edit
		private static readonly HashSet<string> _editedColumns = typeof(PageBlock).GetEntityColumnNames(new string[] {
				"Name",
				"Content"
			}, true);

		/// <summary>
		/// 编辑页面块。
		/// </summary>
		/// <param name="editedBlock">编辑的页面块。</param>
		/// <returns>编辑的页面块。</returns>
		public static PageBlock Edit(PageBlock editedBlock)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();

			PageBlock block = dc.PageBlocks.GetItem(editedBlock.BlockId);
			if (block == null)
				throw new ObjectNotExistsException(Res.Operation_ObjectNotExists);

			GetEditRight(dc, block, true);	// 权限验证

			block.FillByEntity(editedBlock, _editedColumns);

			try
			{
				dc.SubmitChanges(ConflictMode.ContinueOnConflict);
			}
			catch (ChangeConflictException e)
			{
				foreach (ObjectChangeConflict occ in dc.ChangeConflicts)
				{
					occ.Resolve(RefreshMode.KeepCurrentValues);
				}
			}

			// 持久化资源
			InfoItems.SetPersistent(block.GlobalId, true);

			// 注册权限
			RegisterPageBlockEditPermission(block);

			// 记录日志
			Guid? resourceId = dc.PageBlocks.GetBlockEditResourceId(editedBlock.BlockId);
			Logs.Insert(dc, resourceId, (int)PageBlocks.BlockEditPermissionCode.Edit, INFO_TYPE, block.BlockId.ToString(), PageBlocks.BlockEditPermissionCode.Edit.ToString(), block.Name);

			// 返回只读数据
			return editedBlock.FillByEntity(block);
		}
		#endregion
	}



	/// <summary>
	/// PageBlocks 类对应操作权限部分。（受限站点资源。）
	/// </summary>
	public static partial class PageBlocks
	{
		#region GetInsertRight
		/// <summary>
		/// 获取当前用户是否有添加页面块的权限。
		/// </summary>
		/// <param name="dc">数据容器。</param>
		/// <param name="block">添加的页面块对象。</param>
		/// <param name="triggerException">当未通过权限验证的时候是否引发异常。</param>
		/// <returns>布尔值表示当前用户是否有添加页面块的权限。</returns>
		public static bool GetInsertRight(GenericModuleDataContext dc, PageBlock block, bool triggerException)
		{
			string userName = Users.CurrentUserName;
			int permissionCode = (int)PermissionCode.Insert;
			bool b = dc.AccessController.GetUserIsHasPermission<PageBlock>(userName, block, ResourceId, permissionCode, block.SiteId);

			if (triggerException && !b)
				throw new PermissionException(userName, block, ResourceId, permissionCode, Res.PermissionExceptionMessage);
			return b;
		}

		/// <summary>
		/// 获取当前用户是否有添加页面块的权限。
		/// </summary>
		/// <param name="block">添加的页面块对象。</param>
		/// <param name="triggerException">当未通过权限验证的时候是否引发异常。</param>
		/// <returns>布尔值表示当前用户是否有添加页面块的权限。</returns>
		public static bool GetInsertRight(PageBlock block, bool triggerException)
		{
			return GetInsertRight(new GenericModuleDataContext(), block, triggerException);
		}

		/// <summary>
		/// 获取当前用户是否有添加页面块的权限。
		/// </summary>
		/// <param name="block">添加的页面块对象。</param>
		/// <returns>布尔值表示当前用户是否有添加页面块的权限。</returns>
		public static bool GetInsertRight(PageBlock block)
		{
			return GetInsertRight(block, false);
		}
		#endregion



		#region GetUpdateRight
		/// <summary>
		/// 获取当前用户是否有更新页面块的权限。
		/// </summary>
		/// <param name="dc">数据容器。</param>
		/// <param name="block">更新的页面块对象。</param>
		/// <param name="triggerException">当未通过权限验证的时候是否引发异常。</param>
		/// <returns>布尔值表示当前用户是否有更新页面块的权限。</returns>
		public static bool GetUpdateRight(GenericModuleDataContext dc, PageBlock block, bool triggerException)
		{
			string userName = Users.CurrentUserName;
			int permissionCode = (int)PermissionCode.Update;
			bool b = dc.AccessController.GetUserIsHasPermission<PageBlock>(userName, block, ResourceId, permissionCode, block.SiteId);

			if (triggerException && !b)
				throw new PermissionException(userName, block, ResourceId, permissionCode, Res.PermissionExceptionMessage);
			return b;
		}

		/// <summary>
		/// 获取当前用户是否有更新页面块的权限。
		/// </summary>
		/// <param name="block">更新的页面块对象。</param>
		/// <param name="triggerException">当未通过权限验证的时候是否引发异常。</param>
		/// <returns>布尔值表示当前用户是否有更新页面块的权限。</returns>
		public static bool GetUpdateRight(PageBlock block, bool triggerException)
		{
			return GetUpdateRight(new GenericModuleDataContext(), block, triggerException);
		}

		/// <summary>
		/// 获取当前用户是否有更新页面块的权限。
		/// </summary>
		/// <param name="block">更新的页面块对象。</param>
		/// <returns>布尔值表示当前用户是否有更新页面块的权限。</returns>
		public static bool GetUpdateRight(PageBlock block)
		{
			return GetUpdateRight(block, false);
		}
		#endregion



		#region GetDeleteRight
		/// <summary>
		/// 获取当前用户是否有删除页面块的权限。
		/// </summary>
		/// <param name="dc">数据容器。</param>
		/// <param name="block">删除的页面块对象。</param>
		/// <param name="triggerException">当未通过权限验证的时候是否引发异常。</param>
		/// <returns>布尔值表示当前用户是否有删除页面块的权限。</returns>
		public static bool GetDeleteRight(GenericModuleDataContext dc, PageBlock block, bool triggerException)
		{
			string userName = Users.CurrentUserName;
			int permissionCode = (int)PermissionCode.Delete;
			bool b = dc.AccessController.GetUserIsHasPermission<PageBlock>(userName, block, ResourceId, permissionCode, block.SiteId);

			if (triggerException && !b)
				throw new PermissionException(userName, block, ResourceId, permissionCode, Res.PermissionExceptionMessage);
			return b;
		}

		/// <summary>
		/// 获取当前用户是否有删除页面块的权限。
		/// </summary>
		/// <param name="block">删除的页面块对象。</param>
		/// <param name="triggerException">当未通过权限验证的时候是否引发异常。</param>
		/// <returns>布尔值表示当前用户是否有删除页面块的权限。</returns>
		public static bool GetDeleteRight(PageBlock block, bool triggerException)
		{
			return GetDeleteRight(new GenericModuleDataContext(), block, triggerException);
		}

		/// <summary>
		/// 获取当前用户是否有删除页面块的权限。
		/// </summary>
		/// <param name="block">删除的页面块对象。</param>
		/// <returns>布尔值表示当前用户是否有删除页面块的权限。</returns>
		public static bool GetDeleteRight(PageBlock block)
		{
			return GetDeleteRight(block, false);
		}
		#endregion



		#region GetEditRight
		/// <summary>
		/// 获取当前用户是否有编辑页面块的权限。
		/// </summary>
		/// <param name="dc">数据容器。</param>
		/// <param name="block">编辑的页面块对象。</param>
		/// <param name="triggerException">当未通过权限验证的时候是否引发异常。</param>
		/// <returns>布尔值表示当前用户是否有编辑页面块的权限。</returns>
		public static bool GetEditRight(GenericModuleDataContext dc, PageBlock block, bool triggerException)
		{
			string userName = Users.CurrentUserName;
			int permissionCode = (int)BlockEditPermissionCode.Edit;
			Guid? resourceId = dc.PageBlocks.GetBlockEditResourceId(block);
			if (!resourceId.HasValue)
				throw new ObjectNotExistsException(Res.Resources_NotExistsResource);

			bool b = dc.AccessController.GetUserIsHasPermission<PageBlock>(userName, block, resourceId.Value, permissionCode, block.SiteId);

			if (triggerException && !b)
				throw new PermissionException(userName, block, resourceId.Value, permissionCode, Res.PermissionExceptionMessage);
			return b;
		}

		/// <summary>
		/// 获取当前用户是否有编辑页面块的权限。
		/// </summary>
		/// <param name="block">编辑的页面块对象。</param>
		/// <param name="triggerException">当未通过权限验证的时候是否引发异常。</param>
		/// <returns>布尔值表示当前用户是否有编辑页面块的权限。</returns>
		public static bool GetEditRight(PageBlock block, bool triggerException)
		{
			return GetEditRight(new GenericModuleDataContext(), block, triggerException);
		}

		/// <summary>
		/// 获取当前用户是否有编辑页面块的权限。
		/// </summary>
		/// <param name="block">编辑的页面块对象。</param>
		/// <returns>布尔值表示当前用户是否有编辑页面块的权限。</returns>
		public static bool GetEditRight(PageBlock block)
		{
			return GetEditRight(block, false);
		}
		#endregion
	}




	/// <summary>
	/// PageBlocks 类后台管理部分。
	/// </summary>
	public static partial class PageBlocks
	{
		public static bool GetManageListRight()
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			return dc.AccessController.GetUserIsHasPermission<object>(Users.CurrentUserName, null, PageBlocks.ResourceId, (int)PageBlocks.PermissionCode.Update, App.Context.CurrentSiteId);
		}

		public static bool GetEditListRight()
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			return dc.AccessController.GetUserIsHasCategoryPermission<object>(Users.CurrentUserName, null, PageBlocks.BlockEditResourceCategoryId, (int)PageBlocks.BlockEditPermissionCode.Edit, App.Context.CurrentSiteId);
		}

		public static bool GetEditListRight(int? siteId)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			return dc.AccessController.GetUserIsHasCategoryPermission<object>(Users.CurrentUserName, null, PageBlocks.BlockEditResourceCategoryId, (int)PageBlocks.BlockEditPermissionCode.Edit, siteId);
		}



		public class PageBlockForManageList
		{
			public int SiteId { get; set; }
			public int BlockId { get; set; }
			public string Code { get; set; }
			public string Name { get; set; }
			public DateTime CreationDate { get; set; }
		}

		public static PaginationInfo<List<PageBlockForManageList>> GetPaginationManageList(int? siteId, string keyword, int pageSize, int currentPage)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;

			var q = from p in dc.PageBlocks
					where p.IsHidden == false
					select p;

			if (siteId.HasValue)
				q = q.Where(p => p.SiteId == siteId.Value);
			if (!string.IsNullOrEmpty(keyword))
				q = q.Where(p => p.Code.Contains(keyword) || p.Name.Contains(keyword));

			var q2 = q.Select(p => new PageBlockForManageList { SiteId = p.SiteId, BlockId = p.BlockId, Code = p.Code, Name = p.Name, CreationDate = p.CreationDate });

			PaginationInfo<List<PageBlockForManageList>> pageInfo = new PaginationInfo<List<PageBlockForManageList>>();
			pageInfo.PageSize = pageSize;
			pageInfo.CurrentPage = currentPage;
			pageInfo.RecordCount = q2.Count();
			pageInfo.Records = q2.Skip((currentPage - 1) * pageSize).Take(pageSize).ToList();
			return pageInfo;
		}

		public static PaginationInfo<List<PageBlockForManageList>> GetPaginationEditList(int? siteId, string keyword, int pageSize, int currentPage)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;

			string[] blockIds = new string[]{};
			Guid? userId = Users.CurrentUserId;
			if (userId.HasValue)
			{
				int permissionCode = (int)PageBlocks.BlockEditPermissionCode.Edit;

				var q = from p1 in dc.Resources
						from p2 in dc.UserPermissions
						where p1.ResourceId == p2.ResourceId && p1.CategoryId == PageBlocks.BlockEditResourceCategoryId
							&& p2.UserId == userId.Value && p2.PermissionCode == permissionCode && p2.IsEnabled == true
						select new { p1.ResourceCode, p2.SiteId };
				if (siteId.HasValue)
					q = q.Where(p => p.SiteId == null || p.SiteId == siteId.Value);
				else
					q = q.Where(p => p.SiteId == null);
				blockIds = q.Select(p => p.ResourceCode).Distinct().ToArray();
			}

			var q2 = from p in dc.PageBlocks
					 where p.IsHidden == false && blockIds.Contains(p.BlockId.ToString())
					 orderby p.CreationDate ascending, p.BlockId ascending
					 select new PageBlockForManageList { BlockId = p.BlockId, SiteId = p.SiteId, Code = p.Code, Name = p.Name, CreationDate = p.CreationDate };

			if (siteId.HasValue)
				q2 = q2.Where(p => p.SiteId == siteId.Value);
			if (!string.IsNullOrEmpty(keyword))
				q2 = q2.Where(p => p.Code.Contains(keyword) || p.Name.Contains(keyword));

			PaginationInfo<List<PageBlockForManageList>> pageInfo = new PaginationInfo<List<PageBlockForManageList>>();
			pageInfo.PageSize = pageSize;
			pageInfo.CurrentPage = currentPage;
			pageInfo.RecordCount = q2.Count();
			pageInfo.Records = q2.Skip((currentPage - 1) * pageSize).Take(pageSize).ToList();
			return pageInfo;
		}
	}
}